package com.quxue.im.ws;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.quxue.im.common.Const;
import com.quxue.im.entity.ChatUser;
import com.quxue.im.mapper.ChatUserMapper;
import com.quxue.im.service.IChatMsgService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket的文本处理器
 * 有如下情况
 * 1，连接
 * 2，收到消息
 * 3，异常
 * 4，断开连接（下线）
 */
@Component
@Slf4j
public class BootWebSocketHandler extends TextWebSocketHandler {

    @Resource
    private ChatUserMapper chatUserMapper;


    @Resource
    private IChatMsgService chatMsgService;

    /**
     * 创建一个线程安全的map用于存储登录用户
     * key-> 当前登录用户对应的id
     * value-> 当前登录用户产生的WebSocketSession
     */
    private final Map<Long, WebSocketSession> LOGIN_USERS = new ConcurrentHashMap<>();

    /**
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String token = (String) session.getAttributes().get(Const.TOKEN);
        System.out.println("连接成功-----------session = " + session);
        //使用当前用户
        String userId = (String) StpUtil.getLoginIdByToken(token);
        System.out.println("userId = " + userId);
        LOGIN_USERS.put(Long.valueOf(userId), session);
        System.out.println("=========上线==========");
        printOnlineUserInfo();

        //拉取所有离线消息
        chatMsgService.pullMsg(Long.valueOf(userId));
    }

    /**
     * 打印在线用户信息
     */
    public void printOnlineUserInfo() {
        Set<Long> userIds = LOGIN_USERS.keySet();
        if (CollUtil.isNotEmpty(userIds)) {
            List<ChatUser> chatUsers = chatUserMapper.selectBatchIds(userIds);
            System.out.println("============在线用户before============");
            for (ChatUser chatUser : chatUsers) {
                System.out.println("昵称：" + chatUser.getNickName() + ",用户id：" + chatUser.getUserId());
            }
            System.out.println("============在线用户end============");
        }

    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
//        System.out.println("收到消息----------"+message.getPayload());

    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("出现异常--------" + session);
        closeSession(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        System.out.println("下线------" + session);
        closeSession(session);

    }

    public void closeSession(WebSocketSession session) {

        if (session.isOpen()) {
            try {
                session.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        String token = (String) session.getAttributes().get(Const.TOKEN);
        String loginId = (String) StpUtil.getLoginIdByToken(token);
        //使用当前用户
        if (StrUtil.isNotBlank(loginId)) {
            Long userId = Long.parseLong(loginId);
            System.out.println("userId = " + userId);
            if (LOGIN_USERS.containsKey(userId)) {
                //从登录map中删除
                LOGIN_USERS.remove(userId);
            }

            System.out.println("=========下线==========");
            printOnlineUserInfo();
        }


    }

    public void sendMsg(Long userId, String content) {

        WebSocketSession webSocketSession = LOGIN_USERS.get(userId);

        if (Objects.nonNull(webSocketSession) && webSocketSession.isOpen()) {
            try {
                log.info("userId: {} content: {},session : {}", userId, content, webSocketSession);
                System.out.println("webSocketSession = " + webSocketSession);
                webSocketSession.sendMessage(new TextMessage(content));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}
